home *** CD-ROM | disk | FTP | other *** search
- /*
- * fitline.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* FITLINE: program fits lines to data
- * usage: fitline infile outimg [-c] [-L]
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <images.h>
- #include <tiffimage.h>
- #include "pcc2.h" /* for PCC programs */
- extern void print_sos_lic ();
-
- unsigned char *fcCode; /* code storage */
- long nByteCode; /* no. bytes in code storage */
-
- long xytoline (struct point *, long *, long *, long *);
- extern short eigenline (struct point *, long, double *, double *);
- int mbtoendpts (struct point, struct point, double, double,
- long, long, struct point *, struct point *);
- long usage (short);
- long input (int, char **, short *);
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- Image *imgO; /* pointer to output image structure */
- unsigned char **image; /* output image array */
- long width, height; /* image size */
- struct point imgSize; /* image size */
- short coordFlag; /* flag = 1, print fit coord.s; or 0 */
- struct point *data; /* data curve */
- long nData; /* no. coords in data curve */
- long nSegments; /* number of segments found */
- long nStructs; /* number of line structures found */
- long drawline8 (); /* joins points in 8-connected lines */
- struct edge edge; /* lower/upper indices of segment in data */
- short inLine; /* flag = 1 if inside line, 0 otherwise */
- long nFits; /* number of line fits */
- double m, b; /* slope and y-intercept of line fit */
- short eigenline (), fitFlag; /* eigenline returns flag=1 if fit made */
- struct point pt1, pt2; /* endpoints of line fit */
- long iPt; /* index on data for line fits */
- long x, y;
- long i;
-
- /* user input */
- if (input (argc, argv, &coordFlag) < 0)
- return (-1);
-
- /* open input PCC file */
- if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
- exit (1);
- if (coordFlag == 0)
- printf ("image size: %dx%d, PCC length = %d\n", width, height, nByteCode);
- imgSize.x = width;
- imgSize.y = height;
-
- /* allocate output image */
- imgO = ImageAlloc (height, width, 8);
- image = ImageGetPtr (imgO);
-
- /* initialize image */
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- image[y][x] = 255;
-
- /* allocate space for data coordinate array */
- if ((data = (struct point *)
- calloc (nByteCode * MAXPERCODE, sizeof (long))) == NULL) {
- printf ("FITPOLYG: not enough memory -- sorry");
- return (-1);
- }
-
- /* construct tables of feature chain decodes */
- pccdecodes ();
-
- /* perform feature chain decoding */
- pcc2xy (data, &nData);
-
- data[nData++].x = -STOPCODE;
- if ((data = (struct point *)
- realloc (data, nData * sizeof (struct point))) == NULL) {
- printf ("FITPOLYG: not enough memory -- sorry");
- return (-2);
- }
-
- /* find x,y coordinates for each segment */
- if (xytoline (data, &nData, &nSegments, &nStructs) < 0)
- return (-1);
-
- /* fit line to each segment */
- for (i = 0, iPt = 0, inLine = 0, nFits = 0; i < nData; i++) {
- if (data[i].x < 0) {
- if (inLine == 0) {
- edge.iLow = i + 1;
- inLine = 1;
- }
- else {
- --i;
- edge.iHigh = i;
- --iPt;
- fitFlag = eigenline (data, iPt + 1, &m, &b);
- nFits++;
- if (fitFlag) {
- mbtoendpts (data[0], data[iPt], m, b, width, height, &pt1, &pt2);
- if (coordFlag)
- printf ("%d: (%d,%d) (%d,%d)\n",
- nFits, pt1.x, pt1.y, pt2.x, pt2.y);
- drawline8 (image, imgSize, pt1, pt2, 0);
- }
- iPt = 0;
- inLine = 0;
- }
- }
- else {
- data[iPt].x = data[i].x;
- data[iPt++].y = data[i].y;
- }
- }
-
- if (coordFlag == 0)
- printf ("Number of segments fit to data = %d.\n", nFits);
-
- /* write image output file */
- ImageOut (argv[2], imgO);
-
- return (0);
- }
-
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- long
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("USAGE: fitline infile outimg [-c] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\nfitline fits straight lines to pixel chain segments\n");
- printf ("using the eigenvector fit method.\n");
- printf ("NOTE: The fit is performed to each complete line segment;\n");
- printf (" a segment is a chain of points between features, either\n");
- printf (" endpoint features or junction features.\n");
- printf ("NOTE: this fit is not appropriate to approximate curve or corner\n");
- printf (" features within segments -- use a critical point fit or\n");
- printf (" polygonalization fit for this case, instead.\n\n");
- printf ("ARGUMENTS:\n");
- printf (" infile: input filename (PCC)\n");
- printf (" outimg: output image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -c: when set, print line coordinates.\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &coordFlag)
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long
- input (argc, argv, coordFlag)
- int argc;
- char *argv[];
- short *coordFlag; /* flag = 1 to list lines; 0 otherwise */
- {
- long n;
-
- if (argc == 1)
- USAGE_EXIT (1);
- if (argc == 2)
- USAGE_EXIT (0);
-
- *coordFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-c") == 0)
- *coordFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
- return (0);
- }
-